﻿/*********************************************************************
 *
 *                             NOTICE
 *               COPYRIGHT (c) 2012 Panoscopix Software, Inc.
 *                UNPUBLISHED - ALL RIGHTS RESERVED
 * 
 *      This program is confidential, proprietary, and a trade
 *   secret of Panoscopix Software, Inc. The receipt or possession of
 *     this program does not convey any rights to reproduce or
 *      disclose its contents, or to manufacture, use, or sell
 *       anything that it may describe, in whole or in part, 
 *   without the specific written consent of Panoscopix Software, Inc.
 *
 * Implementation of Input Processor using State Pattern to manage
 * the modes of normal and in-macro-definition.
 * 
 *******************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FileSystem.Utility;
using FileSystem.impl.Commands;
using FileSystem.impl;

namespace FileSystem.Impl
{
	class InputProcessor : IInputProcessor
	{
		public InputProcessor()
		{
			//Intentionally empty.
		}

		public String getPrompt()
		{

			string dirPath = string.Empty;
			if (AppResources.getInstance().getFileSystem().CurrentDirectory != null)
			{
				dirPath = AppResources.getInstance().getFileSystem().CurrentDirectory.getFQName();
			}

			if(dirPath.Length > 1 && dirPath.EndsWith("/"))
			{
				dirPath = dirPath.Substring(0, dirPath.Length - 1);
			}
			return "Prompt:" + dirPath + ">";
		}

		public bool process(String input)
		{
			doProcessInput(input);
			return true;
		}

		private void doProcessInput(String input)
		{
			AppResources resources = AppResources.getInstance();
			IOutputSink outx = resources.getOutput();
			String firstToken = StringUtil.firstToken(input);
			String remainder = StringUtil.remainder(input);

			if (resources.getActionFactory().hasName(firstToken))
			{
				doProcessAction(firstToken, remainder);
			}
			else if (resources.getCommandFactory().hasName(firstToken))
			{
				doProcessCommand(firstToken, remainder);
			}
			else
			{
				outx.println("[ERR]Sorry, the registry does not know command '" + firstToken + "'.");
			}
		}

		private void doProcessCommand(string firstToken, string remainder)
		{
			AppResources resources = AppResources.getInstance();
			IOutputSink outx = resources.getOutput();

			ICommand c = null;
			try
			{
				if (remainder.Length == 0)
				{
					c = resources.getCommandFactory().create(firstToken);
				}
				else
				{
					c = resources.getCommandFactory().create(firstToken, remainder);
				}
				if (null != c)
				{
                    bool isMacroModeRunning =  InterceptCommand(c);
                    if (isMacroModeRunning == false)
                    {
                        IResult result = c.execute();
                        resources.getManager().done().push(c);
                        if (result.isResultError())
                        {
                            outx.print("[ERR]");
                        }
                        if (result.isResultEmpty())
                        {
                            outx.println("[EMPTY]");
                        }
                        else
                        {
                            outx.println(result.getResult());
                        }
                    }
				}
				else
				{
					outx.println("[ERR]Sorry, I know command '" + firstToken + "' but it was not created with args '" + remainder + "'.");
				}
			}
			catch (Exception e)
			{
				outx.println(e.Message);
			}
		}

		private void doProcessAction(string firstToken, string remainder)
		{
			AppResources resources = AppResources.getInstance();
			IOutputSink outx = resources.getOutput();
            IFSFileSystem fileSystem = AppResources.getInstance().getFileSystem();
            List<Result> results;
			IAction c = null;
			try
			{
				if (remainder.Length == 0)
				{
					c = resources.getActionFactory().create(firstToken);
				}
				else
				{
					c = resources.getActionFactory().create(firstToken, remainder);
				}
                if (null != c)
                {
                    if (InterceptAction(c, firstToken, remainder) == false)
                    {
                        IResult result = c.execute();

                        if (result.isResultError())
                        {
                            outx.print("[ERR]");
                        }
                        if (result.isResultEmpty())
                        {
                            outx.println("[EMPTY]");
                        }
                        else
                        {
                            outx.println(result.getResult());
                        }
                        results = fileSystem.AsyncResults.ToList();
                        foreach (Result asyncresult in results)
                        {
                            outx.println(asyncresult.getResult());
                            fileSystem.AsyncResults.Remove(asyncresult);
                        }
                    }

                }
                else
                {
                    outx.println("[ERR]Sorry, I know command '" + firstToken + "' but it was not created with args '" + remainder + "'.");
                }
			}
			catch (Exception e)
			{
				outx.println(e.Message);
			}
		}

        private bool InterceptCommand(ICommand command)
        {
            bool isMacroModeRunning = false;
            IFSFileSystem fileSystem = AppResources.getInstance().getFileSystem();
            if (!string.IsNullOrEmpty(fileSystem.ActiveMacroName))
            {
                ProcessMacro(command);
                isMacroModeRunning = true;
            }

            return isMacroModeRunning;
          
        }

        private bool InterceptAction(IAction action, string firstToken, string macroName)
        {
           IFSFileSystem fileSystem = AppResources.getInstance().getFileSystem();
           bool isMacroModeRunning = false;

           if (!string.IsNullOrEmpty(fileSystem.ActiveMacroName) && !string.Equals(firstToken, "end-macro"))
           {
               ProcessMacro(new ExtendedAction(action));
               isMacroModeRunning = true;
           }

           return isMacroModeRunning;
        }

        private void ProcessMacro(ICommand command)
        {
            IFSFileSystem fileSystem = AppResources.getInstance().getFileSystem();
            IMacroDefintion macroDefintion = fileSystem.MacroDefintion[fileSystem.ActiveMacroName];
            macroDefintion.CommandList.Add(command);

        }

	}
}
